using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace GomokuGame.AI
{
    /// <summary>
    /// 中级AI - 专业五子棋战术算法
    /// </summary>
    public class IntermediateAI : IAIAlgorithm
    {
        private readonly Random random = new Random();
        private int thinkingProgress = 0;

        public AIDifficulty Difficulty => AIDifficulty.Intermediate;
        public string Name => "中级AI";

        public async Task<Move> CalculateNextMoveAsync(PieceType[,] board, PieceType currentPlayer, int maxThinkingTime = 5000)
        {
            return await Task.Run(() => CalculateNextMove(board, currentPlayer, maxThinkingTime));
        }

        public Move CalculateNextMove(PieceType[,] board, PieceType currentPlayer, int maxThinkingTime = 5000)
        {
            var startTime = DateTime.Now;
            thinkingProgress = 0;

            // 获取所有可用的空位置
            var availableMoves = GetAvailableMoves(board);
            
            if (availableMoves.Count == 0)
                return null;

            // 开局阶段：使用基础开局策略
            if (IsOpeningPhase(board))
            {
                var openingMove = GetOpeningMove(board, currentPlayer);
                if (openingMove.Row >= 0 && openingMove.Col >= 0)
                {
                    return new Move(openingMove.Row, openingMove.Col, currentPlayer, 1000, 100);
                }
            }

            // 评估每个位置的分数
            var scoredMoves = new List<ScoredMove>();
            
            foreach (var move in availableMoves)
            {
                var score = EvaluateMoveAdvanced(board, move, currentPlayer);
                scoredMoves.Add(new ScoredMove(move, score));
            }

            // 按分数排序，选择最佳的几个位置
            scoredMoves.Sort((a, b) => b.Score.CompareTo(a.Score));
            
            // 从前3个最佳位置中随机选择一个（增加一些随机性）
            var topMoves = scoredMoves.Take(Math.Min(3, scoredMoves.Count)).ToList();
            var selectedMove = topMoves[random.Next(topMoves.Count)];

            // 模拟思考时间
            SimulateThinkingTime(maxThinkingTime);

            var thinkingTime = (int)(DateTime.Now - startTime).TotalMilliseconds;
            thinkingProgress = 100;

            return new Move(selectedMove.Position.Row, selectedMove.Position.Col, currentPlayer, selectedMove.Score, thinkingTime);
        }

        public int GetThinkingProgress()
        {
            return thinkingProgress;
        }

        public void Reset()
        {
            thinkingProgress = 0;
        }

        /// <summary>
        /// 检查是否为开局阶段
        /// </summary>
        private bool IsOpeningPhase(PieceType[,] board)
        {
            int pieceCount = 0;
            int boardSize = board.GetLength(0);
            
            for (int row = 0; row < boardSize; row++)
            {
                for (int col = 0; col < boardSize; col++)
                {
                    if (board[row, col] != PieceType.Empty)
                        pieceCount++;
                }
            }

            return pieceCount <= 6; // 前6手为开局
        }

        /// <summary>
        /// 获取开局移动
        /// </summary>
        private Position GetOpeningMove(PieceType[,] board, PieceType currentPlayer)
        {
            int boardSize = board.GetLength(0);
            int center = boardSize / 2;

            // 第一手：天元
            if (IsFirstMove(board))
            {
                return new Position(center, center);
            }

            // 第二手：星位
            if (IsSecondMove(board))
            {
                var starPositions = new[]
                {
                    new Position(center - 3, center - 3),
                    new Position(center - 3, center + 3),
                    new Position(center + 3, center - 3),
                    new Position(center + 3, center + 3)
                };

                foreach (var pos in starPositions)
                {
                    if (board[pos.Row, pos.Col] == PieceType.Empty)
                        return pos;
                }
            }

            // 其他开局：靠近已有棋子
            return GetNearbyMove(board, currentPlayer);
        }

        /// <summary>
        /// 检查是否为第一手
        /// </summary>
        private bool IsFirstMove(PieceType[,] board)
        {
            int boardSize = board.GetLength(0);
            for (int row = 0; row < boardSize; row++)
            {
                for (int col = 0; col < boardSize; col++)
                {
                    if (board[row, col] != PieceType.Empty)
                        return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 检查是否为第二手
        /// </summary>
        private bool IsSecondMove(PieceType[,] board)
        {
            int pieceCount = 0;
            int boardSize = board.GetLength(0);
            
            for (int row = 0; row < boardSize; row++)
            {
                for (int col = 0; col < boardSize; col++)
                {
                    if (board[row, col] != PieceType.Empty)
                        pieceCount++;
                }
            }

            return pieceCount == 1;
        }

        /// <summary>
        /// 获取靠近已有棋子的移动
        /// </summary>
        private Position GetNearbyMove(PieceType[,] board, PieceType currentPlayer)
        {
            var availableMoves = GetAvailableMoves(board);
            var nearbyMoves = new List<Position>();

            foreach (var move in availableMoves)
            {
                if (HasNearbyPieces(board, move))
                {
                    nearbyMoves.Add(move);
                }
            }

            if (nearbyMoves.Count > 0)
            {
                return nearbyMoves[random.Next(nearbyMoves.Count)];
            }

            return availableMoves[random.Next(availableMoves.Count)];
        }

        /// <summary>
        /// 检查位置附近是否有棋子
        /// </summary>
        private bool HasNearbyPieces(PieceType[,] board, Position position)
        {
            int boardSize = board.GetLength(0);
            
            for (int row = Math.Max(0, position.Row - 2); row <= Math.Min(boardSize - 1, position.Row + 2); row++)
            {
                for (int col = Math.Max(0, position.Col - 2); col <= Math.Min(boardSize - 1, position.Col + 2); col++)
                {
                    if (board[row, col] != PieceType.Empty)
                        return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 获取所有可用的空位置
        /// </summary>
        private List<Position> GetAvailableMoves(PieceType[,] board)
        {
            var moves = new List<Position>();
            int boardSize = board.GetLength(0);

            for (int row = 0; row < boardSize; row++)
            {
                for (int col = 0; col < boardSize; col++)
                {
                    if (board[row, col] == PieceType.Empty)
                    {
                        moves.Add(new Position(row, col));
                    }
                }
            }

            return moves;
        }

        /// <summary>
        /// 高级移动评估
        /// </summary>
        private double EvaluateMoveAdvanced(PieceType[,] board, Position move, PieceType currentPlayer)
        {
            double score = 0;
            int boardSize = board.GetLength(0);

            // 临时放置棋子
            board[move.Row, move.Col] = currentPlayer;

            // 检查是否能获胜
            if (CheckWin(board, move.Row, move.Col, currentPlayer))
            {
                score += 100000; // 获胜分数最高
            }

            // 检查是否能阻止对手获胜
            var opponent = currentPlayer == PieceType.Black ? PieceType.White : PieceType.Black;
            board[move.Row, move.Col] = opponent;
            if (CheckWin(board, move.Row, move.Col, opponent))
            {
                score += 50000; // 阻止对手获胜也很重要
            }

            // 恢复空位置
            board[move.Row, move.Col] = PieceType.Empty;

            // 评估位置价值
            score += EvaluatePositionAdvanced(board, move, currentPlayer);

            // 评估连子潜力
            score += EvaluateLinePotentialAdvanced(board, move, currentPlayer);

            // 评估防守价值
            score += EvaluateDefensiveValueAdvanced(board, move, currentPlayer);

            // 评估威胁空间
            score += EvaluateThreatSpace(board, move, currentPlayer);

            // 评估连接价值
            score += EvaluateConnectionValue(board, move, currentPlayer);

            return score;
        }

        /// <summary>
        /// 高级位置评估
        /// </summary>
        private double EvaluatePositionAdvanced(PieceType[,] board, Position move, PieceType currentPlayer)
        {
            double score = 0;
            int boardSize = board.GetLength(0);

            // 中心位置更有价值
            int center = boardSize / 2;
            int distanceFromCenter = Math.Abs(move.Row - center) + Math.Abs(move.Col - center);
            score += (boardSize - distanceFromCenter) * 15;

            // 检查周围是否有己方棋子
            for (int dr = -1; dr <= 1; dr++)
            {
                for (int dc = -1; dc <= 1; dc++)
                {
                    if (dr == 0 && dc == 0) continue;

                    int newRow = move.Row + dr;
                    int newCol = move.Col + dc;

                    if (newRow >= 0 && newRow < boardSize && newCol >= 0 && newCol < boardSize)
                    {
                        if (board[newRow, newCol] == currentPlayer)
                            score += 80; // 靠近己方棋子
                        else if (board[newRow, newCol] != PieceType.Empty)
                            score += 30; // 靠近对手棋子
                    }
                }
            }

            return score;
        }

        /// <summary>
        /// 高级连子潜力评估
        /// </summary>
        private double EvaluateLinePotentialAdvanced(PieceType[,] board, Position move, PieceType currentPlayer)
        {
            double score = 0;
            int boardSize = board.GetLength(0);

            // 临时放置棋子
            board[move.Row, move.Col] = currentPlayer;

            // 检查四个方向的连子情况
            var directions = new[] { (0, 1), (1, 0), (1, 1), (1, -1) };

            foreach (var (dr, dc) in directions)
            {
                var lineAnalysis = AnalyzeLine(board, move, dr, dc, currentPlayer);
                score += lineAnalysis.ThreatValue;
            }

            // 恢复空位置
            board[move.Row, move.Col] = PieceType.Empty;

            return score;
        }

        /// <summary>
        /// 高级防守价值评估
        /// </summary>
        private double EvaluateDefensiveValueAdvanced(PieceType[,] board, Position move, PieceType currentPlayer)
        {
            double score = 0;
            var opponent = currentPlayer == PieceType.Black ? PieceType.White : PieceType.Black;

            // 临时放置棋子
            board[move.Row, move.Col] = currentPlayer;

            // 检查四个方向的防守情况
            var directions = new[] { (0, 1), (1, 0), (1, 1), (1, -1) };

            foreach (var (dr, dc) in directions)
            {
                var lineAnalysis = AnalyzeLine(board, move, dr, dc, opponent);
                
                // 根据对手威胁程度给分
                if (lineAnalysis.LiveFour) score += 10000;  // 阻止对手活四
                if (lineAnalysis.SleepFour) score += 5000;  // 阻止对手眠四
                if (lineAnalysis.LiveThree) score += 1000;  // 阻止对手活三
                if (lineAnalysis.SleepThree) score += 500;  // 阻止对手眠三
                if (lineAnalysis.LiveTwo) score += 100;     // 阻止对手活二
                if (lineAnalysis.SleepTwo) score += 50;     // 阻止对手眠二
            }

            // 恢复空位置
            board[move.Row, move.Col] = PieceType.Empty;

            return score;
        }

        /// <summary>
        /// 评估威胁空间
        /// </summary>
        private double EvaluateThreatSpace(PieceType[,] board, Position move, PieceType currentPlayer)
        {
            double score = 0;
            var directions = new[] { (0, 1), (1, 0), (1, 1), (1, -1) };

            // 临时放置棋子
            board[move.Row, move.Col] = currentPlayer;

            foreach (var (dr, dc) in directions)
            {
                // 检查这个方向上的威胁潜力
                int forwardCount = CountInDirection(board, move.Row, move.Col, dr, dc, currentPlayer);
                int backwardCount = CountInDirection(board, move.Row, move.Col, -dr, -dc, currentPlayer);
                int totalCount = forwardCount + backwardCount - 1;

                // 根据连子数量给分
                switch (totalCount)
                {
                    case 4: score += 2000; break; // 四连
                    case 3: score += 200; break;  // 三连
                    case 2: score += 20; break;   // 二连
                }
            }

            // 恢复空位置
            board[move.Row, move.Col] = PieceType.Empty;

            return score;
        }

        /// <summary>
        /// 评估连接价值
        /// </summary>
        private double EvaluateConnectionValue(PieceType[,] board, Position move, PieceType currentPlayer)
        {
            double score = 0;
            int boardSize = board.GetLength(0);

            // 检查是否能连接己方棋子
            for (int dr = -2; dr <= 2; dr++)
            {
                for (int dc = -2; dc <= 2; dc++)
                {
                    if (dr == 0 && dc == 0) continue;

                    int newRow = move.Row + dr;
                    int newCol = move.Col + dc;

                    if (newRow >= 0 && newRow < boardSize && newCol >= 0 && newCol < boardSize)
                    {
                        if (board[newRow, newCol] == currentPlayer)
                        {
                            score += 60 / (Math.Abs(dr) + Math.Abs(dc)); // 距离越近价值越高
                        }
                    }
                }
            }

            return score;
        }

        /// <summary>
        /// 分析连线情况
        /// </summary>
        private LineAnalysis AnalyzeLine(PieceType[,] board, Position pos, int dr, int dc, PieceType player)
        {
            var analysis = new LineAnalysis();
            int boardSize = board.GetLength(0);

            // 临时放置棋子
            board[pos.Row, pos.Col] = player;

            // 计算连续棋子
            int forwardCount = CountInDirection(board, pos.Row, pos.Col, dr, dc, player);
            int backwardCount = CountInDirection(board, pos.Row, pos.Col, -dr, -dc, player);
            int totalCount = forwardCount + backwardCount - 1;

            // 检查两端是否被封堵
            bool forwardBlocked = IsBlocked(board, pos.Row + dr * forwardCount, pos.Col + dc * forwardCount);
            bool backwardBlocked = IsBlocked(board, pos.Row - dr * backwardCount, pos.Col - dc * backwardCount);

            // 计算活棋和眠棋
            if (totalCount >= 5)
            {
                analysis.ThreatValue = 100000; // 五连
            }
            else if (totalCount == 4)
            {
                if (!forwardBlocked && !backwardBlocked)
                {
                    analysis.ThreatValue = 10000; // 活四
                    analysis.LiveFour = true;
                }
                else if (!forwardBlocked || !backwardBlocked)
                {
                    analysis.ThreatValue = 5000; // 眠四
                    analysis.SleepFour = true;
                }
            }
            else if (totalCount == 3)
            {
                if (!forwardBlocked && !backwardBlocked)
                {
                    analysis.ThreatValue = 1000; // 活三
                    analysis.LiveThree = true;
                }
                else if (!forwardBlocked || !backwardBlocked)
                {
                    analysis.ThreatValue = 500; // 眠三
                    analysis.SleepThree = true;
                }
            }
            else if (totalCount == 2)
            {
                if (!forwardBlocked && !backwardBlocked)
                {
                    analysis.ThreatValue = 100; // 活二
                    analysis.LiveTwo = true;
                }
                else if (!forwardBlocked || !backwardBlocked)
                {
                    analysis.ThreatValue = 50; // 眠二
                    analysis.SleepTwo = true;
                }
            }

            // 恢复空位置
            board[pos.Row, pos.Col] = PieceType.Empty;

            return analysis;
        }

        /// <summary>
        /// 检查位置是否被封堵
        /// </summary>
        private bool IsBlocked(PieceType[,] board, int row, int col)
        {
            int boardSize = board.GetLength(0);
            return row < 0 || row >= boardSize || col < 0 || col >= boardSize || board[row, col] != PieceType.Empty;
        }

        /// <summary>
        /// 检查是否获胜
        /// </summary>
        private bool CheckWin(PieceType[,] board, int row, int col, PieceType pieceType)
        {
            if (CountInDirection(board, row, col, 0, 1, pieceType) + CountInDirection(board, row, col, 0, -1, pieceType) - 1 >= 5)
                return true;

            if (CountInDirection(board, row, col, 1, 0, pieceType) + CountInDirection(board, row, col, -1, 0, pieceType) - 1 >= 5)
                return true;

            if (CountInDirection(board, row, col, 1, 1, pieceType) + CountInDirection(board, row, col, -1, -1, pieceType) - 1 >= 5)
                return true;

            if (CountInDirection(board, row, col, 1, -1, pieceType) + CountInDirection(board, row, col, -1, 1, pieceType) - 1 >= 5)
                return true;

            return false;
        }

        /// <summary>
        /// 在指定方向上计算连续棋子数量
        /// </summary>
        private int CountInDirection(PieceType[,] board, int row, int col, int deltaRow, int deltaCol, PieceType pieceType)
        {
            int count = 0;
            int currentRow = row;
            int currentCol = col;
            int boardSize = board.GetLength(0);

            while (currentRow >= 0 && currentRow < boardSize && currentCol >= 0 && currentCol < boardSize && 
                   board[currentRow, currentCol] == pieceType)
            {
                count++;
                currentRow += deltaRow;
                currentCol += deltaCol;
            }

            return count;
        }

        /// <summary>
        /// 模拟思考时间
        /// </summary>
        private void SimulateThinkingTime(int maxTime)
        {
            var actualTime = random.Next(300, Math.Min(maxTime, 2500)); // 300ms到2.5秒之间
            var steps = 20;
            var stepTime = actualTime / steps;

            for (int i = 0; i < steps; i++)
            {
                System.Threading.Thread.Sleep(stepTime);
                thinkingProgress = (i + 1) * 100 / steps;
            }
        }

        /// <summary>
        /// 位置结构
        /// </summary>
        private struct Position
        {
            public int Row { get; set; }
            public int Col { get; set; }

            public Position(int row, int col)
            {
                Row = row;
                Col = col;
            }
        }

        /// <summary>
        /// 带分数的移动结构
        /// </summary>
        private struct ScoredMove
        {
            public Position Position { get; set; }
            public double Score { get; set; }

            public ScoredMove(Position position, double score)
            {
                Position = position;
                Score = score;
            }
        }

        /// <summary>
        /// 连线分析结构
        /// </summary>
        private struct LineAnalysis
        {
            public double ThreatValue { get; set; }
            public bool LiveFour { get; set; }
            public bool SleepFour { get; set; }
            public bool LiveThree { get; set; }
            public bool SleepThree { get; set; }
            public bool LiveTwo { get; set; }
            public bool SleepTwo { get; set; }
        }
    }
} 